package com.qinbaokeji.checkpoint.dahuacamera.listener;

import com.alibaba.fastjson.JSONObject;
import com.qinbaokeji.checkpoint.dahuacamera.common.Res;
import com.qinbaokeji.checkpoint.dahuacamera.config.MyUncaughtExceptionHandler;
import com.qinbaokeji.checkpoint.dahuacamera.entity.CameraInfo;
import com.qinbaokeji.checkpoint.dahuacamera.entity.LogInfo;
import com.qinbaokeji.checkpoint.dahuacamera.entity.ResultObj;
import com.qinbaokeji.checkpoint.dahuacamera.lib.NetSDKLib;
import com.qinbaokeji.checkpoint.dahuacamera.lib.ToolKits;
import com.qinbaokeji.checkpoint.dahuacamera.module.AlarmListenModule;
import com.qinbaokeji.checkpoint.dahuacamera.module.LoginModule;
import com.qinbaokeji.checkpoint.dahuacamera.service.ILogInfoService;
import com.qinbaokeji.checkpoint.dahuacamera.service.ServiceFactory;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;


public class AlarmListener {
//	private static final String IP = "192.168.1.108";
//	private static final Integer PORT = 37777;
//	private static final String USER = "admin";
//	private static final String PASSWORD = "qbkj8888";
	private static final RestTemplate restTemplate = new RestTemplate();
//	private String sendUrl;
//	private String uuid;
	private CameraInfo cameraInfo;
	private static Logger logger = LoggerFactory.getLogger(AlarmListener.class);

	public CameraInfo getCameraInfo(){
		return cameraInfo;
	}

//	public AlarmListener() throws IOException {
//		start();
//	}

	/**
	 * 初始化设备
	 */
	public void  init(){
		if (!LoginModule.init(new DisConnect(), new HaveReConnect())){
			logger.error("初始化设备失败");
			throw new RuntimeException("初始化设备失败");
		}
	}

	//登录摄像
	public boolean login(CameraInfo camera) {
		if(LoginModule.login(
				camera.getIp(),
				camera.getPort(),
				camera.getUsername(),
				camera.getPassword())) {

		} else {
			logger.error("登录失败："+Res.string().getLoginFailed() + ", " + ToolKits.getErrorCodeShow()+", "+Res.string().getErrorMessage());
			throw new RuntimeException("登录失败："+Res.string().getLoginFailed() + ", " + ToolKits.getErrorCodeShow()+", "+Res.string().getErrorMessage());
		}
		return true;
	}

	//摄像头退出登录
	public void logout() {
		AlarmListenModule.stopListen();
		LoginModule.logout();
		LoginModule.cleanup();
	}

	//监听警报
	public boolean listen(){
		if(AlarmListenModule.startListen(cbMessage)){
			logger.info("监听成功");
		}else{
			logger.error("监听失败");
			throw new RuntimeException("监听失败");
		}
		return true;
	}

	//停止监听
	public void stopListen(){
		AlarmListenModule.stopListen();
	}


	public void start(CameraInfo camera) throws IOException {
		this.cameraInfo = camera;
		//初始化设备
		LoginModule.init(new DisConnect(), new HaveReConnect());
		/**
		 * 1、进行登录操作
		 * 2、进行报警监听
		 */
		if (login(camera)){
			listen();
		}
        while (true){}
	}

	public void send(String plate){
	    try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
			MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
			form.add("veName", plate);
			form.add("camera", this.cameraInfo.getUuid());
			HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(form, headers);
            restTemplate.postForObject(this.cameraInfo.getSendUrl(),requestEntity,String.class);
//            ResultObj resultObj = JSONObject.parseObject(response, ResultObj.class);
//			System.out.println(resultObj);
        }catch (Exception e){
            logger.error("车牌发送错误",e);
        }
	}







	/////////////////以下是大华功能区域：function///////////////////
	////JNA Callback方法定义,断线回调
	private class DisConnect implements NetSDKLib.fDisConnect {
		public DisConnect() { }
		public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
			System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);
			LogInfo logInfo = new LogInfo()
					.getConnectLog("com.qinbaokeji.checkpoint.dahuacamera.listener.AlarmListener.DisConnect.invoke()",
							"尝试重连",
							pchDVRIP,
							nDVRPort+"");
			ILogInfoService iLogInfoService = (ILogInfoService) ServiceFactory.getService("iLogInfoService");
			iLogInfoService.save(logInfo);
		}
	}

	// device reconnect(success) callback class
	// 网络连接恢复回调函数原形
	private static class HaveReConnect implements NetSDKLib.fHaveReConnect {
		public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
			logger.info("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort);
			LogInfo logInfo = new LogInfo()
					.getConnectLog("com.qinbaokeji.checkpoint.dahuacamera.listener.AlarmListener.HaveReConnect.invoke()",
							"重连成功",
							pchDVRIP,
							nDVRPort+"");
			ILogInfoService iLogInfoService = (ILogInfoService) ServiceFactory.getService("iLogInfoService");
			iLogInfoService.save(logInfo);
		}
	}

	private AlarmListener.fAlarmDataCB cbMessage = new AlarmListener.fAlarmDataCB();
	// alarm listen data callback
	private class fAlarmDataCB implements NetSDKLib.fMessCallBack{

		@Override
		public boolean invoke(int lCommand, NetSDKLib.LLong lLoginID,
							  Pointer pStuEvent, int dwBufLen, String strDeviceIP,
							  NativeLong nDevicePort, Pointer dwUser) {

			System.out.println(lCommand);
			System.out.println(pStuEvent);
			switch (lCommand) {
				//监听到车辆事件
				case 13382:{
					NetSDKLib.DEV_EVENT_TRAFFICJUNCTION_INFO msg = new NetSDKLib.DEV_EVENT_TRAFFICJUNCTION_INFO();
					ToolKits.GetPointerData(pStuEvent, msg);
					try {
						trafficInfo.m_PlateNumber = new String(msg.stuObject.szText, "GBK").trim();
//						System.out.println(trafficInfo.m_PlateNumber);
						String plate = trafficInfo.m_PlateNumber.replaceAll("\\ufffd","").replaceAll("\u0000","");
						logger.info("车牌号码："+plate);
//						System.out.println(plate);
						send(plate);
					} catch (UnsupportedEncodingException e) {
						logger.error("车牌解析失败",e);
						e.printStackTrace();
					}
					break;
				}
				default:
					break;
			}
			return true;
		}

	}

	enum AlarmStatus {
		ALARM_START, ALARM_STOP
	}

	// struct of alarm event
	static class AlarmEventInfo {
		public static long index = 0;
		public long id;
		public int chn;
		public int type;
		public Date date;
		public AlarmStatus status;

		public AlarmEventInfo(int chn, int type, AlarmStatus status) {
			this.chn = chn;
			this.type = type;
			this.status = status;
			this.date = new Date();
		}

		@Override
		public boolean equals(Object o) {
			if (this == o) return true;
			if (o == null || getClass() != o.getClass()) return false;
			AlarmEventInfo showInfo = (AlarmEventInfo) o;
			return chn == showInfo.chn && type == showInfo.type;
		}
	}

	private class TRAFFIC_INFO {
		private String m_EventName;         	  // 事件名称
		private String m_PlateNumber;       	  // 车牌号
		private String m_PlateType;               // 车牌类型
		private String m_PlateColor;      	  	  // 车牌颜色
		private String m_VehicleColor;    	  	  // 车身颜色
		private String m_VehicleType;       	  // 车身类型
		private String m_VehicleSize;     	  	  // 车辆大小
		private String m_FileCount;				  // 文件总数
		private String m_FileIndex;				  // 文件编号
		private String m_GroupID;				  // 组ID
		private String m_IllegalPlace;			  // 违法地点
		private String m_LaneNumber;              // 通道号
		private NetSDKLib.NET_TIME_EX m_Utc;      // 事件时间
		private int m_bPicEnble;       	  		  // 车牌对应信息，BOOL类型
		private int m_OffSet;          	  		  // 车牌偏移量
		private int m_FileLength;                 // 文件大小
		private NetSDKLib.DH_RECT m_BoundingBox;  // 包围盒
	}

	private final TRAFFIC_INFO trafficInfo = new TRAFFIC_INFO();

	public static void main(String[] args) throws IOException {
//		new AlarmListener().start();

	}
}
